package stone.ast;

import java.util.List;

import ASTInterpreter.Environment;
import stone.StoneException;

public class Arguments extends Postfix {

	public Arguments(List<ASTree> list) {
		super(list);
	}
	
	public int size() {
		return numChildren();
	}

	public Object eval(Environment callerEnv, Object value) {
		if (value instanceof NativeFunction) {
			return nativeFuncEval(callerEnv, value);
		}
		return funcEval(callerEnv, value);
	}
	
	private Object nativeFuncEval(Environment callerEnv, Object value) {
		NativeFunction func = (NativeFunction)value;
		int nparams = func.numOfParameters();
		if (size() != nparams) {
			throw new StoneException("bad number of arguments", this);
		}
		Object[] args = new Object[nparams];
		int num = 0;
		for (ASTree a : this) {
			args[num++] = a.eval(callerEnv);
		}
		return func.invoke(args, this);
	}
	
	private Object funcEval(Environment callerEnv, Object value) {
		if (!(value instanceof Function)) {
			throw new StoneException("bad function", this);
		}

		Function func = (Function)value;
		ParameterList params = func.parameters();
		if (size() != params.size()) {
			throw new StoneException("bad number of arguments", this);
		}

		Environment newEnv = func.makeEnv();
		int num = 0;
		for (ASTree a : this) {
			((ParameterList)params).eval(newEnv, num++, a.eval(callerEnv));
		}

		return func.body().eval(newEnv);
	}

}
